package com.miniapp.controller;

import com.github.vioao.wechat.api.component.AccountApi;
import com.github.vioao.wechat.api.component.wxa.CodeApi;
import com.github.vioao.wechat.bean.response.BaseResponse;
import com.miniapp.conifg.wechatOpen.WechatDomainProperties;
import com.miniapp.constant.SysConstants;
import com.miniapp.entity.MiniProductEntity;
import com.miniapp.entity.MiniUserProductEntity;
import com.miniapp.entity.enums.MiniVersionStatus;
import com.miniapp.exception.RRException;
import com.miniapp.service.MiniProductService;
import com.miniapp.service.MiniUserProductService;
import com.miniapp.service.MiniUserService;
import com.miniapp.service.MiniVersionLogService;
import com.miniapp.service.impl.WxOpenService;
import com.miniapp.utils.BaseUtils;
import com.miniapp.utils.R;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import weixin.popular.api.WxaAPI;
import weixin.popular.bean.BaseResult;
import weixin.popular.bean.wxa.ModifyDomain;
import weixin.popular.bean.wxa.ModifyDomainResult;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created with IntelliJ IDEA.
 * User: linyuchi
 * Date: 2018/4/22
 * Time: 11:06
 * Description:  微信开放平台第三方授权类
 */
@RestController
@RequestMapping("/open")
public class OpenWeChatController extends AbstractController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    protected WxOpenService wxOpenService;
    @Autowired
    protected WechatDomainProperties wechatDomainProperties;
    @Autowired
    private MiniUserProductService miniUserProductService;
    @Autowired
    private MiniProductService miniProductService;

    @RequestMapping("/ticket")
    public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp,
                                @RequestParam("nonce") String nonce, @RequestParam("signature") String signature,
                                @RequestParam(name = "encrypt_type", required = false) String encType,
                                @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        this.logger.info(
                "\n接收微信请求：[signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                signature, encType, msgSignature, timestamp, nonce, requestBody);

        if (!StringUtils.equalsIgnoreCase("aes", encType) || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        // aes加密的消息
        WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody, wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
        this.logger.info("\n消息解密后内容为：\n{} ", inMessage.toString());
        try {
            //如果用户主动去掉授权，将删除用户授权信息
            if(StringUtils.equals(inMessage.getInfoType(), "unauthorized")){
                MiniUserProductEntity miniUserProduct =  miniUserProductService.findByWxAppid(inMessage.getAuthorizerAppid());
                if (BaseUtils.isNotEmpty(miniUserProduct)){
                    miniUserProductService.changeStatus(miniUserProduct,MiniVersionStatus.DOWN);
                }
            }else  if(StringUtils.equals(inMessage.getInfoType(), "updateauthorized")){
                MiniUserProductEntity miniUserProduct =  miniUserProductService.findByWxAppid(inMessage.getAuthorizerAppid());
                if (BaseUtils.isNotEmpty(miniUserProduct)){
                    miniUserProductService.changeStatus(miniUserProduct,MiniVersionStatus.UP);
                }
            }
            String out = wxOpenService.getWxOpenComponentService().route(inMessage);
            this.logger.info("\n组装回复信息：{}", out);
        } catch (WxErrorException e) {
            this.logger.error("receive_ticket", e);
        }
        return "success";
    }

    @RequestMapping("/{appId}/callback")
    public Object callback(@RequestBody(required = false) String requestBody,
                           @PathVariable("appId") String appId,
                           @RequestParam("signature") String signature,
                           @RequestParam("timestamp") String timestamp,
                           @RequestParam("nonce") String nonce,
                           @RequestParam("openid") String openid,
                           @RequestParam("encrypt_type") String encType,
                           @RequestParam("msg_signature") String msgSignature) {
        this.logger.info(
                "\n接收微信请求：[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
        if (!StringUtils.equalsIgnoreCase("aes", encType) || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        String out = "";
        // aes加密的消息
        WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody, wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
        this.logger.info("\n消息解密后内容为：\n{} ", inMessage.toString());

        // 全网发布测试用例
//        if (StringUtils.equalsAnyIgnoreCase(appId, SysConstants.COMPONENT_APP_ID)) {
        try {
            if (StringUtils.equals(inMessage.getMsgType(), "text")) {
                if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) {
                    out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
                            WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback")
                                    .fromUser(inMessage.getToUser())
                                    .toUser(inMessage.getFromUser())
                                    .build(),
                            wxOpenService.getWxOpenConfigStorage()
                    );
                } else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) {
                    String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
                    WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build();
                    wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
                }else{
                    logger.info("接入客服："+inMessage.getContent());
                    out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
                            WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE()
                                    .fromUser(inMessage.getToUser())
                                    .toUser(inMessage.getFromUser())
                                    .build(),
                            wxOpenService.getWxOpenConfigStorage()
                    );
                }
            } else if (StringUtils.equals(inMessage.getMsgType(), "event")) {
                //获取审核结果
                if (inMessage.getEvent().equals("weapp_audit_success")){
                    logger.info("审核通过"+inMessage);
                    //更新审核状态
                    MiniUserProductEntity miniUserProduct =  miniUserProductService.findByWxGhId(inMessage.getToUser());
                    miniUserProductService.changeStatus(miniUserProduct, MiniVersionStatus.PASS);
                    //直接发布版本
                    String accessToken = wxOpenService.getWxOpenComponentService().getAuthorizerAccessToken(miniUserProduct.getWxAppid(),true);
                    BaseResponse baseResponse  = CodeApi.release(accessToken);
                    logger.info("发布后信息："+baseResponse.toString());
                    if (!baseResponse.isSuccess()){
                        miniUserProductService.changeStatus(miniUserProduct,MiniVersionStatus.UP_PUBLISH);
                    }else {
                        miniUserProductService.changeStatus(miniUserProduct,MiniVersionStatus.PUBLISH);
                    }


                }
                //获取审核结果
                else if (inMessage.getEvent().equals("weapp_audit_fail")){
                    logger.info("审核失败"+inMessage);
                    //更新审核状态
                    MiniUserProductEntity miniUserProduct =  miniUserProductService.findByWxGhId(inMessage.getToUser());
                    miniUserProductService.changeStatus(miniUserProduct,MiniVersionStatus.UN_PASS);

                }
                else {
                    logger.info("进入客服提示"+inMessage.getEvent());
                    WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content("您好！").toUser(inMessage.getFromUser()).build();
                    wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
                }

            }
        } catch (WxErrorException e) {
            logger.error("callback", e);
        }
//        }else{
//            logger.info("执行发送"+inMessage);
//            WxMpXmlOutMessage outMessage = wxOpenService.getWxOpenMessageRouter().route(inMessage, appId);
//            if(outMessage != null){
//                out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(outMessage, wxOpenService.getWxOpenConfigStorage());
//            }
//        }
        return out;
    }

    /**
     * 获取跳转链接地址
     */
    @GetMapping("/auth/goto_auth_url")
    @ResponseBody
    public R getAuthUrl()  {

        String url = SysConstants.VENICE_BACK_URL + "/open/auth/auth_url?appid="+this.getAppid();
        return R.ok().put("url",url);
    }

    /**
     * 微信跳转到预授权页面地址
     * @return
     */
    @GetMapping("/auth/auth_url")
    public void gotoPreAuthUrl(HttpServletResponse response,String appid) throws IOException {

        String url = SysConstants.VENICE_BACK_URL + "/open/auth/jump?appid="+appid;
        try {
            url = wxOpenService.getWxOpenComponentService().getPreAuthUrl(url);
        } catch (WxErrorException e) {
            logger.error("gotoPreAuthUrl", e);
            throw new RuntimeException(e);
        }
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        StringBuffer sbHtml = new StringBuffer();
        sbHtml.append("<!doctype html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
        sbHtml.append("</head><body></body>");
        sbHtml.append("<script type=\"text/javascript\"> \n" +
                "function onloadHref() \n" +
                "{ \n" +
                " window.location.href= '"+url+"' \n" +
                "} \n" +
                "window.onload=onloadHref(); \n" +
                "</script></html> ");
        out.write(sbHtml.toString());

    }
    @GetMapping("/auth/jump")
    public void jump(@RequestParam("auth_code") String authorizationCode, HttpServletResponse response,@RequestParam("appid") String appid){
        try {
            WxOpenQueryAuthResult queryAuthResult = wxOpenService.getWxOpenComponentService().getQueryAuth(authorizationCode);

            logger.info("扫码成功后APPID"+appid);
            WxOpenAuthorizerInfoResult wxOpenAuthorizerInfoResult =  wxOpenService.getWxOpenComponentService()
                    .getAuthorizerInfo(queryAuthResult.getAuthorizationInfo().getAuthorizerAppid());

            //扫码成功后将用户小程序设置为已接入，更改信息
            MiniUserProductEntity miniUserProduct = miniUserProductService.findByAppid(appid);
            logger.info("扫码成功后回调数据"+wxOpenAuthorizerInfoResult.toString());
            //微信ID
            String wxAppID = wxOpenAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAppid();
            logger.info("获得wxappid"+wxAppID);
            //原始ID
            String ghId = wxOpenAuthorizerInfoResult.getAuthorizerInfo().getUserName();
            if (BaseUtils.isEmpty(miniUserProduct)){
                throw new RRException("访问异常");
            }
            boolean flag  = miniUserProductService.isBand(wxAppID,miniUserProduct.getId());

            if (!flag){
                throw new RRException("该小程序已经被绑定");
            }
            //绑定小程序
//            if (BaseUtils.isEmpty(miniUserProduct)||miniUserProduct.getBuyUserId()!=this.getUserId()){
//                throw new RRException("访问异常");
//            }
//            String accessToken = wxOpenService.getWxOpenComponentService().getAuthorizerAccessToken(miniUserProduct.getWxAppid(),true);
//            BaseResponse bindRes  = AccountApi.bind(queryAuthResult.getAuthorizationInfo().getAuthorizerAccessToken(),miniUserProduct.getWxAppid(), SysConstants.COMPONENT_APP_ID);
//
//            if (bindRes.isSuccess()){
//                logger.info("绑定成功！");
//            }else{
//                logger.info("绑定失败："+bindRes.getErrcode()+bindRes.getErrmsg());
//            }

//            //设置小程序服务域名
            ModifyDomain domain = new ModifyDomain("set",wechatDomainProperties.getRequestdomain(),
                    wechatDomainProperties.getWsrequestdomain(),wechatDomainProperties.getUploaddomain(),
                    wechatDomainProperties.getDownloaddomain());

            ModifyDomainResult baseResponse = WxaAPI.modify_domain(queryAuthResult.getAuthorizationInfo().getAuthorizerAccessToken(),domain);

            //设置服务域名
            miniUserProduct.setWxAppid(wxAppID);
            miniUserProduct.setStatus(MiniVersionStatus.UP);
            miniUserProduct.setWxGhId(ghId);
            miniUserProductService.updateById(miniUserProduct);
            //通过用户获取用户代理人的路径
            String host = SysConstants.VENICE_URL;

            MiniProductEntity miniProductEntity = miniProductService.getById(miniUserProduct.getProductId());

            String code = miniProductEntity.getCode();

            response.sendRedirect(host+ "/#/"+code+"/overview-data");
        } catch (WxErrorException | IOException e) {
            logger.error("gotoPreAuthUrl", e);
            throw new RuntimeException(e);
        }
    }


}
